Convert ggv_bin format to sub-class of Format (#462)
authorRalf Horstmann <ralf+github@ackstorm.de>
Tue, 21 Jan 2020 22:10:34 +0000 (23:10 +0100)
committertsteven4 <13596209+tsteven4@users.noreply.github.com>
Tue, 21 Jan 2020 22:10:34 +0000 (15:10 -0700)
* Convert ggv_bin format to sub-class of Format

* Add ggv_bin helpers as class member functions

* Style improvements in ggv_bin

CMakeLists.txt
GPSBabel.pro
Makefile.in
ggv_bin.cc
ggv_bin.h [new file with mode: 0644]
vecs.h

index 673e38abf192ccc12a3bb61c37c282676863100f..1a34bbaaf3ce162704854a7ae0fa8a9852cc1068 100644 (file)
@@ -123,6 +123,7 @@ set(HEADERS
   gbser.h
   gbser_private.h
   gbversion.h
+  ggv_bin.h
   gpx.h
   grtcirc.h
   heightgrid.h
index 13b2cf4165e9fd3f10624b13f12f77f4c7412058..89ed1eb3d22de2304a92ab9ad5bd336707572b1d 100644 (file)
@@ -111,6 +111,7 @@ HEADERS =  \
        gbser.h \
        gbser_private.h \
        gbversion.h \
+       ggv_bin.h \
        gpx.h \
        grtcirc.h \
        heightgrid.h \
index aa1ba71f1c555a9d4bb774b8a23b2a6f881d72f1..90e2fd249e10123bd53ea3c6c7bfb4fe78875a8b 100644 (file)
@@ -581,7 +581,8 @@ geojson.o: geojson.cc defs.h config.h zlib/zlib.h zlib/zconf.h cet.h \
   inifile.h gbfile.h session.h src/core/datetime.h src/core/optional.h \
   src/core/file.h
 ggv_bin.o: ggv_bin.cc defs.h config.h zlib/zlib.h zlib/zconf.h cet.h \
-  inifile.h gbfile.h session.h src/core/datetime.h src/core/optional.h
+  inifile.h gbfile.h session.h src/core/datetime.h src/core/optional.h \
+  ggv_bin.h format.h
 ggv_log.o: ggv_log.cc defs.h config.h zlib/zlib.h zlib/zconf.h cet.h \
   inifile.h gbfile.h session.h src/core/datetime.h src/core/optional.h \
   grtcirc.h
@@ -1008,7 +1009,8 @@ vcf.o: vcf.cc defs.h config.h zlib/zlib.h zlib/zconf.h cet.h inifile.h \
 vecs.o: vecs.cc defs.h config.h zlib/zlib.h zlib/zconf.h cet.h inifile.h \
   gbfile.h session.h src/core/datetime.h src/core/optional.h vecs.h \
   format.h gpx.h src/core/file.h src/core/xmlstreamwriter.h \
-  src/core/xmltag.h legacyformat.h gbversion.h src/core/logging.h xcsv.h
+  src/core/xmltag.h legacyformat.h gbversion.h src/core/logging.h xcsv.h \
+  ggv_bin.h
 vidaone.o: vidaone.cc defs.h config.h zlib/zlib.h zlib/zconf.h cet.h \
   inifile.h gbfile.h session.h src/core/datetime.h src/core/optional.h
 vitosmt.o: vitosmt.cc defs.h config.h zlib/zlib.h zlib/zconf.h cet.h \
index bba7a3628cb31ce2bdef4dc2b8ba271c2c0822c0..8d244128a1760567c505b7e44a043194c895ab53 100644 (file)
@@ -2,8 +2,8 @@
 
     Handle Geogrid-Viewer binary overlay file format (.ovl)
 
-    Copyright (C) 2016 Ralf Horstmann <ralf@ackstorm.de>
-    Copyright (C) 2016 Robert Lipe, robertlipe+source@gpsbabel.org
+    Copyright (C) 2016-2020 Ralf Horstmann <ralf@ackstorm.de>
+    Copyright (C) 2016-2020 Robert Lipe, robertlipe+source@gpsbabel.org
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 
 */
 
-#include "defs.h"
 #include <QtCore/QByteArray>
 #include <QtCore/QDataStream>
 #include <QtCore/QDebug>
 #include <QtCore/QFile>
 #include <QtCore/QtEndian>
 
-#define MYNAME "ggv_bin"
+#include "ggv_bin.h"
 
-static QString read_fname;
+#define MYNAME "ggv_bin"
 
 /***************************************************************************
  *           local helper functions                                        *
  ***************************************************************************/
 
-static void
-ggv_bin_read_bytes(QDataStream& stream, QByteArray& buf, int len, const char* descr = nullptr)
+void
+GgvBinFormat::ggv_bin_read_bytes(QDataStream& stream, QByteArray& buf, int len, const char* descr)
 {
-  if (len < 0)
+  if (len < 0) {
     fatal(MYNAME ": Read error, negative len (%s)\n", descr ? descr : "");
+  }
   buf.resize(len);
-  if (stream.readRawData(buf.data(), len) != len || stream.status() != QDataStream::Ok)
+  if (stream.readRawData(buf.data(), len) != len || stream.status() != QDataStream::Ok) {
     fatal(MYNAME ": Read error (%s)\n", descr ? descr : "");
+  }
 }
 
-static quint16
-ggv_bin_read16(QDataStream& stream, const char* descr = nullptr)
+quint16
+GgvBinFormat::ggv_bin_read16(QDataStream& stream, const char* descr)
 {
   quint16 res;
   stream >> res;
-  if (stream.status() != QDataStream::Ok)
+  if (stream.status() != QDataStream::Ok) {
     fatal(MYNAME ": Read error (%s)\n", descr ? descr : "");
-  if (global_opts.debug_level > 1)
+  }
+  if (global_opts.debug_level > 1) {
     qDebug("ovl: %-15s %5u (0x%04x)", descr, res, res);
+  }
   return res;
 }
 
-static quint32
-ggv_bin_read32(QDataStream& stream, const char* descr = nullptr)
+quint32
+GgvBinFormat::ggv_bin_read32(QDataStream& stream, const char* descr)
 {
   quint32 res;
   stream >> res;
-  if (stream.status() != QDataStream::Ok)
+  if (stream.status() != QDataStream::Ok) {
     fatal(MYNAME ": Read error (%s)\n", descr ? descr : "");
+  }
   if (global_opts.debug_level > 1) {
-    if ((res & 0xFFFF0000) == 0) 
+    if ((res & 0xFFFF0000) == 0) {
       qDebug("ovl: %-15s %5u (0x%08x)", descr, res, res);
-    else
+    } else {
       qDebug("ovl: %-15s       (0x%08x)", descr, res);
+    }
   }
   return res;
 }
 
-static void
-ggv_bin_read_text16(QDataStream& stream, QByteArray& buf, const char* descr = nullptr)
+void
+GgvBinFormat::ggv_bin_read_text16(QDataStream& stream, QByteArray& buf, const char* descr)
 {
   quint16 len = ggv_bin_read16(stream, descr);
   ggv_bin_read_bytes(stream, buf, len, descr);
   buf[len] = 0;
-  if (global_opts.debug_level > 1)
+  if (global_opts.debug_level > 1) {
     qDebug() << "ovl: text =" << QString::fromLatin1(buf.constData()).simplified();
+  }
 }
 
-static void
-ggv_bin_read_text32(QDataStream& stream, QByteArray& buf, const char* descr = nullptr)
+void
+GgvBinFormat::ggv_bin_read_text32(QDataStream& stream, QByteArray& buf, const char* descr)
 {
   quint32 len = ggv_bin_read32(stream, descr);
   // The following check prevents passing an unsigned int with a
   // value greater than INT32_MAX to a signed int parameter in
   // ggv_bin_read_bytes later on. If this happens, the file is
   // almost certainly corrupted.
-  if (len > INT32_MAX)
+  if (len > INT32_MAX) {
     fatal(MYNAME ": Read error, max len exceeded (%s)\n", descr ? descr : "");
+  }
   ggv_bin_read_bytes(stream, buf, len, descr);
   buf[len] = 0;
-  if (global_opts.debug_level > 1)
+  if (global_opts.debug_level > 1) {
     qDebug() << "ovl: text =" << QString::fromLatin1(buf.constData()).simplified();
+  }
 }
 
-static double
-ggv_bin_read_double(QDataStream& stream, const char* descr = nullptr)
+double
+GgvBinFormat::ggv_bin_read_double(QDataStream& stream, const char* descr)
 {
   double res;
   stream >> res;
-  if (stream.status() != QDataStream::Ok)
+  if (stream.status() != QDataStream::Ok) {
     fatal(MYNAME ": Read error (%s)\n", descr ? descr : "");
+  }
   return res;
 }
 
@@ -114,8 +123,8 @@ ggv_bin_read_double(QDataStream& stream, const char* descr = nullptr)
  *            OVL Version 2.0                                              *
  ***************************************************************************/
 
-static void
-ggv_bin_read_v2(QDataStream& stream)
+void
+GgvBinFormat::ggv_bin_read_v2(QDataStream& stream)
 {
   QByteArray buf;
   QString track_name;
@@ -131,15 +140,17 @@ ggv_bin_read_v2(QDataStream& stream)
     ggv_bin_read_bytes(stream, buf, header_len, "map name");
     buf.remove(0,4);
     buf.append('\0');
-    if (global_opts.debug_level > 1)
+    if (global_opts.debug_level > 1) {
       qDebug() << "ovl: name =" << buf.constData();
+    }
   }
 
   while (!stream.atEnd()) {
     track_name.clear();
 
-    if (global_opts.debug_level > 1)
+    if (global_opts.debug_level > 1) {
       qDebug("------------------------------------ 0x%llx", stream.device()->pos());
+    }
 
     auto entry_pos = stream.device()->pos();
     quint16 entry_type = ggv_bin_read16(stream, "entry type");
@@ -171,7 +182,7 @@ ggv_bin_read_v2(QDataStream& stream)
       waypt_add(wpt);
       break;
     case 0x03:
-      // line
+    // line
     case 0x04:
       // area
       ggv_bin_read16(stream, "line color");
@@ -180,8 +191,9 @@ ggv_bin_read_v2(QDataStream& stream)
       line_points = ggv_bin_read16(stream, "line points");
       ggv_bin_track = route_head_alloc();
       track_add_head(ggv_bin_track);
-      if (! track_name.isEmpty())
+      if (! track_name.isEmpty()) {
         ggv_bin_track->rte_name = track_name;
+      }
 
       for (int i = 1; i <= line_points; i++) {
         lon = ggv_bin_read_double(stream, "line lon");
@@ -193,9 +205,9 @@ ggv_bin_read_v2(QDataStream& stream)
       }
       break;
     case 0x05:
-      // rectangle
+    // rectangle
     case 0x06:
-      // circle
+    // circle
     case 0x07:
       // triangle
       ggv_bin_read16(stream, "geom color");
@@ -226,8 +238,8 @@ ggv_bin_read_v2(QDataStream& stream)
  *           OVL Version 3.0 and 4.0                                       *
  ***************************************************************************/
 
-static void
-ggv_bin_read_v34_header(QDataStream& stream, quint32& number_labels, quint32 &number_records)
+void
+GgvBinFormat::ggv_bin_read_v34_header(QDataStream& stream, quint32& number_labels, quint32& number_records)
 {
   QByteArray buf;
 
@@ -246,18 +258,20 @@ ggv_bin_read_v34_header(QDataStream& stream, quint32& number_labels, quint32 &nu
     ggv_bin_read_bytes(stream, buf, header_len, "map name");
     buf.remove(0,4);
     buf.append('\0');
-    if (global_opts.debug_level > 1)
+    if (global_opts.debug_level > 1) {
       qDebug() << "ovl: name =" << buf.constData();
+    }
   }
 }
 
-static void
-ggv_bin_read_v34_label(QDataStream& stream)
+void
+GgvBinFormat::ggv_bin_read_v34_label(QDataStream& stream)
 {
   QByteArray buf;
 
-  if (global_opts.debug_level > 1)
+  if (global_opts.debug_level > 1) {
     qDebug("------------------------------------ 0x%llx", stream.device()->pos());
+  }
   ggv_bin_read_bytes(stream, buf, 0x08, "label header");
   ggv_bin_read_bytes(stream, buf, 0x14, "label number");
   ggv_bin_read_text16(stream, buf, "label text");
@@ -265,8 +279,8 @@ ggv_bin_read_v34_label(QDataStream& stream)
   ggv_bin_read16(stream, "label flag2");
 }
 
-static QString
-ggv_bin_read_v34_common(QDataStream& stream)
+QString
+GgvBinFormat::ggv_bin_read_v34_common(QDataStream& stream)
 {
   QByteArray buf;
 
@@ -293,18 +307,19 @@ ggv_bin_read_v34_common(QDataStream& stream)
   return res;
 }
 
-static void
-ggv_bin_read_v34_record(QDataStream& stream)
+void
+GgvBinFormat::ggv_bin_read_v34_record(QDataStream& stream)
 {
   QByteArray buf;
-  Waypoint *wpt;
+  Waypointwpt;
   route_head* ggv_bin_track;
   quint32 bmp_len;
   quint16 line_points;
   double lon, lat;
 
-  if (global_opts.debug_level > 1)
+  if (global_opts.debug_level > 1) {
     qDebug("------------------------------------ 0x%llx", stream.device()->pos());
+  }
 
   quint16 entry_type = ggv_bin_read16(stream, "entry type");
   QString label = ggv_bin_read_v34_common(stream);
@@ -332,14 +347,15 @@ ggv_bin_read_v34_record(QDataStream& stream)
     break;
   case 0x03:
   case 0x04:
-    // area
+  // area
   case 0x17:
     // line
     ggv_bin_track = route_head_alloc();
     track_add_head(ggv_bin_track);
-      
-    if (! label.isEmpty()) 
+
+    if (! label.isEmpty()) {
       ggv_bin_track->rte_name = label;
+    }
 
     ggv_bin_read16(stream, "line prop1");
     ggv_bin_read32(stream, "line prop2");
@@ -397,8 +413,9 @@ ggv_bin_read_v34_record(QDataStream& stream)
     // value greater than INT32_MAX to a signed int parameter in
     // ggv_bin_read_bytes later on. If this happens, the file is
     // almost certainly corrupted.
-    if (bmp_len > INT32_MAX)
+    if (bmp_len > INT32_MAX) {
       fatal(MYNAME ": Read error, max bmp_len exceeded\n");
+    }
     ggv_bin_read16(stream, "bmp prop");
     ggv_bin_read_bytes(stream, buf, bmp_len, "bmp data");
     break;
@@ -407,8 +424,8 @@ ggv_bin_read_v34_record(QDataStream& stream)
   }
 }
 
-static void
-ggv_bin_read_v34(QDataStream& stream)
+void
+GgvBinFormat::ggv_bin_read_v34(QDataStream& stream)
 {
   QByteArray buf;
   quint32 label_count;
@@ -418,31 +435,37 @@ ggv_bin_read_v34(QDataStream& stream)
     ggv_bin_read_v34_header(stream, label_count, record_count);
 
     if (label_count && !stream.atEnd()) {
-      if (global_opts.debug_level > 1)
+      if (global_opts.debug_level > 1) {
         qDebug("-----labels------------------------- 0x%llx", stream.device()->pos());
-      for (unsigned int i = 0; i < label_count; i++)
+      }
+      for (unsigned int i = 0; i < label_count; i++) {
         ggv_bin_read_v34_label(stream);
+      }
     }
 
     if (record_count && !stream.atEnd()) {
-      if (global_opts.debug_level > 1)
+      if (global_opts.debug_level > 1) {
         qDebug("-----records------------------------ 0x%llx", stream.device()->pos());
-      for (unsigned int i = 0; i < record_count; i++)
+      }
+      for (unsigned int i = 0; i < record_count; i++) {
         ggv_bin_read_v34_record(stream);
+      }
     }
 
     if (!stream.atEnd()) {
-      if (global_opts.debug_level > 1)
+      if (global_opts.debug_level > 1) {
         qDebug("------------------------------------ 0x%llx", stream.device()->pos());
+      }
       // we just skip over the next magic bytes without checking they
       // contain the correct string. This is consistent with what I
       // believe GGV does
       ggv_bin_read_bytes(stream, buf, 23, "magicbytes");
-      if (global_opts.debug_level > 1)
+      if (global_opts.debug_level > 1) {
         qDebug() << "ovl: header = " << buf.constData();
+      }
     }
   }
-    
+
   if (global_opts.debug_level > 1) {
     qDebug("fpos: 0x%llx", stream.device()->pos());
     qDebug("size: 0x%llx", stream.device()->size());
@@ -450,14 +473,22 @@ ggv_bin_read_v34(QDataStream& stream)
 }
 
 /***************************************************************************
- *           global callbacks called by gpsbabel main process              *
+ *              entry points called by gpsbabel main process               *
  ***************************************************************************/
 
-static void
-ggv_bin_read_file(QDataStream& stream)
+void
+GgvBinFormat::read()
 {
-  QByteArray buf;
+  QFile file(read_fname);
+  if (!file.open(QIODevice::ReadOnly)) {
+    fatal(MYNAME ": Error opening file %s\n", qPrintable(read_fname));
+  }
 
+  QDataStream stream(&file);
+  stream.setFloatingPointPrecision(QDataStream::DoublePrecision);
+  stream.setByteOrder(QDataStream::LittleEndian);
+
+  QByteArray buf;
   ggv_bin_read_bytes(stream, buf, 0x17, "magic");
   buf[23] = 0;
   if (global_opts.debug_level > 1) {
@@ -473,54 +504,19 @@ ggv_bin_read_file(QDataStream& stream)
   } else {
     fatal(MYNAME ": Unsupported file format\n");
   }
+
+  file.close();
 }
 
-static void
-ggv_bin_read_init(const QString& fname)
+void
+GgvBinFormat::rd_init(const QString& fname)
 {
   read_fname = fname;
 }
 
-static void
-ggv_bin_read_deinit()
+void
+GgvBinFormat::rd_deinit()
 {
   read_fname.clear();
 }
 
-static void
-ggv_bin_read()
-{
-  QFile file(read_fname);
-
-  if (!file.open(QIODevice::ReadOnly)) {
-    fatal(MYNAME ": Error opening file %s\n", qPrintable(read_fname));
-  }
-
-  QDataStream stream(&file);
-  stream.setFloatingPointPrecision(QDataStream::DoublePrecision);
-  stream.setByteOrder(QDataStream::LittleEndian);
-  
-  ggv_bin_read_file(stream);
-  file.close();
-}
-
-ff_vecs_t ggv_bin_vecs = {
-  ff_type_file,
-  {
-    ff_cap_none,  // waypoints
-    ff_cap_read,  // tracks
-    ff_cap_none   // routes
-  },
-  ggv_bin_read_init,    // rd_init
-  nullptr,                 // wr_init
-  ggv_bin_read_deinit,  // rd_deinit
-  nullptr,                 // wr_deinit
-  ggv_bin_read,         // read
-  nullptr,                 // write
-  nullptr,                 // exit
-  nullptr,                 //args
-  CET_CHARSET_ASCII, 0  //encode,fixed_encode
-  //NULL                //name dynamic/internal?
-  , NULL_POS_OPS,
-  nullptr
-};
diff --git a/ggv_bin.h b/ggv_bin.h
new file mode 100644 (file)
index 0000000..6138409
--- /dev/null
+++ b/ggv_bin.h
@@ -0,0 +1,79 @@
+/*
+
+    Handle Geogrid-Viewer binary overlay file format (.ovl)
+
+    Copyright (C) 2016-2020 Ralf Horstmann <ralf@ackstorm.de>
+    Copyright (C) 2016-2020 Robert Lipe, robertlipe+source@gpsbabel.org
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+*/
+#ifndef GGV_BIN_H_INCLUDED_
+#define GGV_BIN_H_INCLUDED_
+
+#include "defs.h"
+#include "format.h"
+
+
+class GgvBinFormat : public Format
+{
+public:
+  ff_type get_type() const override
+  {
+    return ff_type_file;
+  }
+
+  QVector<ff_cap> get_cap() const override
+  {
+    return {
+      ff_cap_none,  // waypoints
+      ff_cap_read,  // tracks
+      ff_cap_none   // routes
+    };
+  }
+
+  QString get_encode() const override
+  {
+    return CET_CHARSET_ASCII;
+  }
+
+  int get_fixed_encode() const override
+  {
+    return 0;
+  }
+
+  void rd_init(const QString& fname) override;
+  void read() override;
+  void rd_deinit() override;
+
+private:
+  static void ggv_bin_read_bytes(QDataStream& stream, QByteArray& buf, int len, const char* descr = nullptr);
+  static quint16 ggv_bin_read16(QDataStream& stream, const char* descr = nullptr);
+  static quint32 ggv_bin_read32(QDataStream& stream, const char* descr = nullptr);
+  static void ggv_bin_read_text16(QDataStream& stream, QByteArray& buf, const char* descr = nullptr);
+  static void ggv_bin_read_text32(QDataStream& stream, QByteArray& buf, const char* descr = nullptr);
+  static double ggv_bin_read_double(QDataStream& stream, const char* descr = nullptr);
+  static void ggv_bin_read_v2(QDataStream& stream);
+  static void ggv_bin_read_v34_header(QDataStream& stream, quint32& number_labels, quint32& number_records);
+  static void ggv_bin_read_v34_label(QDataStream& stream);
+  static QString ggv_bin_read_v34_common(QDataStream& stream);
+  static void ggv_bin_read_v34_record(QDataStream& stream);
+  static void ggv_bin_read_v34(QDataStream& stream);
+
+  QString read_fname;
+
+};
+
+#endif
diff --git a/vecs.h b/vecs.h
index 8369376d5f6638e4ceae5c93422ee60ea45500df..6bb20cd57e2d94735929124bd7c86368391d4a18 100644 (file)
--- a/vecs.h
+++ b/vecs.h
@@ -28,6 +28,7 @@
 
 #include "defs.h"
 #include "format.h"
+#include "ggv_bin.h"
 #include "gpx.h"
 #include "legacyformat.h"
 
@@ -174,7 +175,6 @@ extern ff_vecs_t mapfactor_vecs;
 extern ff_vecs_t energympro_vecs;
 extern ff_vecs_t mynav_vecs;
 extern ff_vecs_t geojson_vecs;
-extern ff_vecs_t ggv_bin_vecs;
 extern ff_vecs_t globalsat_sport_vecs;
 #endif // MAXIMAL_ENABLED
 
@@ -380,7 +380,7 @@ private:
   LegacyFormat energympro_fmt {energympro_vecs};
   LegacyFormat mynav_fmt {mynav_vecs};
   LegacyFormat geojson_fmt {geojson_vecs};
-  LegacyFormat ggv_bin_fmt {ggv_bin_vecs};
+  GgvBinFormat ggv_bin_fmt;
   LegacyFormat globalsat_sport_fmt {globalsat_sport_vecs};
 #endif // MAXIMAL_ENABLED